package com.yy.wga.mp.module.income.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yy.wga.common.core.aop.DistributedLock;
import com.yy.wga.common.core.exception.BusinessException;
import com.yy.wga.mp.common.interceptor.RequestUserHolder;
import com.yy.wga.mp.common.utils.common.IdUtils;
import com.yy.wga.mp.common.utils.common.NumberUtils;
import com.yy.wga.mp.common.utils.common.SpringUtils;
import com.yy.wga.mp.common.utils.date.DateUtils;
import com.yy.wga.mp.module.income.entity.pojo.IncomeUserBalanceDO;
import com.yy.wga.mp.module.income.entity.pojo.IncomeWithdrawRecordDO;
import com.yy.wga.mp.module.income.entity.pojo.IncomeWithdrawSettingDO;
import com.yy.wga.mp.module.income.mapper.IncomeUserBalanceMapper;
import com.yy.wga.mp.module.income.request.IncomeUserBalanceWithdrawRequest;
import com.yy.wga.mp.module.income.service.IncomeUserBalanceService;
import com.yy.wga.mp.module.income.service.IncomeWithdrawRecordService;
import com.yy.wga.mp.module.income.service.IncomeWithdrawSettingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 用户余额(IncomeUserBalance)表服务实现类
 *
 * @author guochao
 * @since 2024-11-12 00:27:47
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class IncomeUserBalanceServiceImpl extends ServiceImpl<IncomeUserBalanceMapper, IncomeUserBalanceDO> implements IncomeUserBalanceService {
    private final IncomeWithdrawRecordService withdrawRecordService;
    private final IncomeWithdrawSettingService withdrawSettingService;

    @Override
    @DistributedLock(value = "'balance:' + #userId")
    @Transactional
    public void withdraw(Long userId, IncomeUserBalanceWithdrawRequest request) {
        IncomeWithdrawSettingDO withdrawSetting = withdrawSettingService.getOne(new LambdaQueryWrapper<IncomeWithdrawSettingDO>()
                .eq(IncomeWithdrawSettingDO::getAppKey, RequestUserHolder.getBaseRequest().getAppKey()));
        if (withdrawSetting == null) {
            throw new BusinessException("未开通提现功能");
        }
        Integer amount = request.getAmount();
        // 最小提现金额
        Integer minAmount = withdrawSetting.getMinAmount();
        if (amount < minAmount) {
            throw new BusinessException("最小提现金额（元）:" + NumberUtils.changeF2Y(minAmount));
        }
        // 每日提现限制
        Date startOfDay = DateUtils.getStartOfDay(new Date());
        List<IncomeWithdrawRecordDO> withdrawRecordList = withdrawRecordService.list(new LambdaQueryWrapper<IncomeWithdrawRecordDO>()
                .eq(IncomeWithdrawRecordDO::getAppKey, RequestUserHolder.getBaseRequest().getAppKey())
                .eq(IncomeWithdrawRecordDO::getUserId, userId)
                .ge(IncomeWithdrawRecordDO::getCreateTime, startOfDay));
        if (!CollectionUtils.isEmpty(withdrawRecordList)) {
            int withdrawAmount = withdrawRecordList.stream()
                    .mapToInt(IncomeWithdrawRecordDO::getAmount).sum();
            withdrawAmount += amount;
            Integer dayLimit = withdrawSetting.getDayLimit();
            if (withdrawAmount > dayLimit) {
                throw new BusinessException("每日最大提现金额（元）:" + NumberUtils.changeF2Y(withdrawAmount));
            }
        }
        // 计算服务费
        BigDecimal serviceCharge = withdrawSetting.getServiceCharge().divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP);
        int serviceChargeAmount = NumberUtils.changeY2F(new BigDecimal(amount).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP).multiply(serviceCharge).doubleValue());

        // 修改提现金额
        IncomeUserBalanceDO userBalance = baseMapper.selectOne(new LambdaQueryWrapper<IncomeUserBalanceDO>()
                .eq(IncomeUserBalanceDO::getAppKey, RequestUserHolder.getBaseRequest().getAppKey())
                .eq(IncomeUserBalanceDO::getUserId, userId));
        if (userBalance == null || userBalance.getSettle() < amount) {
            throw new BusinessException("余额不足");
        }

        // 修改余额
        IncomeUserBalanceServiceImpl bean = SpringUtils.getBean(this.getClass());
        IncomeUserBalanceDO updateUserBalance = new IncomeUserBalanceDO();
        updateUserBalance.setId(userBalance.getId());
        updateUserBalance.setUserId(userBalance.getUserId());
        updateUserBalance.setAppKey(userBalance.getAppKey());
        updateUserBalance.setInWithdraw(amount);
        updateUserBalance.setSettle(-amount);
        bean.incrementIncome(updateUserBalance);

        // 保存提现记录
        IncomeWithdrawRecordDO withdrawRecordDO = new IncomeWithdrawRecordDO();
        withdrawRecordDO.setUserId(userId);
        withdrawRecordDO.setOrderNo(IdUtils.uuid());
        withdrawRecordDO.setAmount(amount);
        withdrawRecordDO.setType(request.getType());
        withdrawRecordDO.setWithdrawAccount(request.getWithdrawAccount());
        withdrawRecordDO.setRealName(request.getRealName());
        withdrawRecordDO.setOpenId(RequestUserHolder.getUserCache().getOpenId());
        withdrawRecordDO.setServiceCharge(serviceChargeAmount);
        withdrawRecordDO.setStatus(0);
        withdrawRecordDO.setAppKey(RequestUserHolder.getBaseRequest().getAppKey());
        withdrawRecordService.save(withdrawRecordDO);
    }

    @Override
    @DistributedLock(value = "'balance:' + #incrementBalance.userId")
    public void incrementIncome(IncomeUserBalanceDO incrementBalance) {
        IncomeUserBalanceDO userBalance = baseMapper.selectOne(new LambdaQueryWrapper<IncomeUserBalanceDO>()
                .eq(IncomeUserBalanceDO::getAppKey, incrementBalance.getAppKey())
                .eq(IncomeUserBalanceDO::getUserId, incrementBalance.getUserId()));
        if (userBalance == null) {
            userBalance = new IncomeUserBalanceDO();
            userBalance.setAppKey(incrementBalance.getAppKey());
            userBalance.setUserId(incrementBalance.getUserId());
            userBalance.setUnSettle(0);
            userBalance.setSettle(0);
            userBalance.setWithdraw(0);
            userBalance.setInWithdraw(0);
            userBalance.setCancel(0);
        }
        if (incrementBalance.getUnSettle() != null) {
            userBalance.setUnSettle(userBalance.getUnSettle() + incrementBalance.getUnSettle());
        }
        if (incrementBalance.getWithdraw() != null) {
            userBalance.setWithdraw(userBalance.getWithdraw() + incrementBalance.getWithdraw());
        }
        if (incrementBalance.getCancel() != null) {
            userBalance.setCancel(userBalance.getCancel() + incrementBalance.getCancel());
        }
        if (incrementBalance.getInWithdraw() != null) {
            userBalance.setInWithdraw(userBalance.getInWithdraw() + incrementBalance.getInWithdraw());
        }
        if (incrementBalance.getSettle() != null) {
            userBalance.setSettle(userBalance.getSettle() + incrementBalance.getSettle());
        }
        this.saveOrUpdate(userBalance);
        log.info("新增用户收益:{}", userBalance.getUserId());
    }
}
